package ace.module.oauth2.server.core.impl.converter.impl;

import ace.module.oauth2.server.core.impl.converter.Oauth2ObjectJsonConverter;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.Module;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.List;
import java.util.Map;
import lombok.SneakyThrows;
import org.springframework.security.jackson2.SecurityJackson2Modules;
import org.springframework.security.oauth2.server.authorization.client.JdbcRegisteredClientRepository;
import org.springframework.security.oauth2.server.authorization.jackson2.OAuth2AuthorizationServerJackson2Module;
import org.springframework.stereotype.Component;

/**
 * @author caspar
 * @date 2023/10/12 11:50
 */
@Component
public class Oauth2ObjectJsonConverterImpl implements Oauth2ObjectJsonConverter {
  private final ObjectMapper objectMapper = new ObjectMapper();
  private static final TypeReference<Map<String, Object>> ATTRIBUTES_TYPE_REFERENCE =
      new TypeReference<>() {};

  public Oauth2ObjectJsonConverterImpl() {
    ClassLoader classLoader = JdbcRegisteredClientRepository.class.getClassLoader();
    List<Module> securityModules = SecurityJackson2Modules.getModules(classLoader);
    this.objectMapper.registerModules(securityModules);
    this.objectMapper.registerModule(new OAuth2AuthorizationServerJackson2Module());
  }

  @SneakyThrows
  @Override
  public String toJson(Object object) {
    return this.objectMapper.writeValueAsString(object);
  }

  @SneakyThrows
  @Override
  public Map<String, Object> toMap(String json) {
    return this.objectMapper.readValue(json, ATTRIBUTES_TYPE_REFERENCE);
  }

  @SneakyThrows
  @Override
  public <T> T toObject(String json, Class<T> cls) {
    return this.objectMapper.readValue(json, cls);
  }
}
